% reweight the particles, and return the list of particles sorted by weight
function particles = reweight(particles, particle_signals, signal, map)
    variance = 16; % standard deviation squared   %TODO: tune
    proportionalityConstant = 1; %TODO: tune
    learningRate = 1;
    
    totalWeights = zeros(length(particle_signals), 1);
    denom = sqrt(2 * pi);
    
    for i = 1:length(signal)
        % formula taken from particle filter slides
        diff = particle_signals(:, i) - signal(i);
        power = -(diff .* diff)./(2 * variance);

        weights = exp(power) .* proportionalityConstant ./ denom;% - dampingFactor;
        % make sure that illegal measurements are weighted 0
        weights(~isfinite(particle_signals(:, i))) = 0;
        % weight particles outside the arena as 0
        weights(~inpolygon(particles(:, 1), particles(:, 2), map(:, 1), map(:, 2))) = 0;
        totalWeights = totalWeights + weights;
    end
    
    averageWeights = totalWeights ./ length(signal);
    
    particles(:, 4) = max(particles(:, 4) .* (1 - learningRate) + averageWeights .* learningRate, 0);
    particles(1, 4);
    particles = sortRows(particles, 4);
    % switch to descending
    particles = flipud(particles);
end